package ch.uzh.ifi.sonar.qacpp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jface.preference.IPreferenceStore;

import ch.uzh.ifi.sonar.Activator;
import ch.uzh.ifi.sonar.storage.PreferenceConstants;

/**
 * Qacpp starter
 * 
 * @author Yi Guo
 * */
public class QacppStarter {

	private String settingFile;

	private String qacppFileLocation;

	private String palFileLocation;

	private String fileListFile;

	/*
	 * public QacppStarter(final String settingFileLocation, final String
	 * qacppFileLocation, final String palFileLocation) {
	 * this.settingFileLocation = settingFileLocation; this.qacppFileLocation =
	 * qacppFileLocation; this.palFileLocation = palFileLocation; }
	 */

	public QacppStarter() {
		// FIXME: Why the preference store does not really store anything?
		// IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		// WORKAROUND: hard coded here
		/* QACPP Analysis */
		// this.qacppFileLocation =
		// store.getString(PreferenceConstants.QACPP_EXE_PATH);
		/* Settings.via */
		// this.settingFileLocation =
		// store.getString(PreferenceConstants.QACPP_SETTING_FILE_PATH);
		this.settingFile = "D:\\sonar_workspace\\sonar_working_settings\\settings.via";
		this.qacppFileLocation = "C:\\\"Program Files\"\\PRQA\\QACPP-2.5.1-R\\bin\\qacpp.exe";
		this.palFileLocation = "C:\\\"Program Files\"\\PRQA\\QACPP-2.5.1-R\\bin\\pal.exe";

		/* CMA Analysis */
		// this.palFileLocation =
		// store.getString(PreferenceConstants.PAL_EXE_PATH);
	}

	public QacppStarter(String settingFile, String fileListFile) {
		this.settingFile = settingFile;
		this.fileListFile = fileListFile;
	}

	public Process executeProcessByStream() {
		if(this.settingFile != null && this.settingFile !=null){
			Runtime runtime = Runtime.getRuntime();
			String execStr = "cmd /c " + this.qacppFileLocation + " -via "
					+ this.settingFile + " -list" + this.fileListFile;
			Process p;
			try {
				p = runtime.exec(execStr);
				// analyze the output of p is essential, otherwise there will be some concurrency problems.
				InputStreamReader stderrReader = new InputStreamReader(
						p.getErrorStream());
				BufferedReader br = new BufferedReader(stderrReader);
				String line = null;
				while ((line = br.readLine()) != null) {
					System.out.println(line);
				}
				int exitValue = p.waitFor();
				System.out.println("qacpp.exe is analyzing... : " + exitValue);
				return p;
			} catch (IOException e) {
				System.out.println("Execute Process Error: " + e.getMessage());
				e.printStackTrace();
			} catch (InterruptedException e) {
				System.out.println("Process Interrupted! " + e.getMessage());
				e.printStackTrace();
			}
		}else{
			System.out.println("[Error: ]Please check QacppStarter's setting file and filelist file!");
		}
		return null;		
	}
	
	public Process executeCMAProcessByStream() {
		if(this.settingFile != null && this.settingFile !=null){
			Runtime runtime = Runtime.getRuntime();
			// pal.exe launch the CMA analysis
			String execStr = "cmd /c " + this.palFileLocation + " -via "
					+ this.settingFile + " -list" + this.fileListFile;
			Process p;
			try {
				p = runtime.exec(execStr);
				// analyze the output of p is essential, otherwise there will be some concurrency problems.
				InputStreamReader stderrReader = new InputStreamReader(
						p.getErrorStream());
				BufferedReader br = new BufferedReader(stderrReader);
				String line = null;
				while ((line = br.readLine()) != null) {
					System.out.println(line);
				}
				int exitValue = p.waitFor();
				System.out.println("qacpp.exe is analyzing... : " + exitValue);
				return p;
			} catch (IOException e) {
				System.out.println("Execute Process Error: " + e.getMessage());
				e.printStackTrace();
			} catch (InterruptedException e) {
				System.out.println("Process Interrupted! " + e.getMessage());
				e.printStackTrace();
			}
		}else{
			System.out.println("[Error: ]Please check QacppStarter's setting file and filelist file!");
		}
		return null;
		
	}

	public Process executeProcess(String fileName, String opFilePath)
			throws InterruptedException {
		Runtime runtime = Runtime.getRuntime();
		String execStr = "cmd /c " + this.qacppFileLocation + " -via "
				+ this.settingFile + " " + fileName;
		try {
			Process p;
			if (opFilePath.isEmpty()) {
				p = runtime.exec(execStr);
			} else {
				p = runtime.exec(execStr + " -op " + opFilePath);
			}
			/*
			 * it is necessary to read process's error stream to make sure
			 * process return the expected value
			 */
			InputStreamReader stderrReader = new InputStreamReader(
					p.getErrorStream());
			BufferedReader br = new BufferedReader(stderrReader);
			String line = null;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}
			int exitValue = p.waitFor();
			System.out.println(fileName + " is analyzing... : " + exitValue);
			return p;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
/** 
 * After CMA analysis precondition has fulfilled */
	public Process executeCMAProcess(String fileName)
			throws InterruptedException {
		Runtime runtime = Runtime.getRuntime();
		/* pal.exe options... */
		String execStr = "cmd /c " + this.palFileLocation;
		try {
			Process p = runtime.exec(execStr);
			InputStreamReader stderrReader = new InputStreamReader(
					p.getErrorStream());
			BufferedReader br = new BufferedReader(stderrReader);
			String line = null;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}
			int exitValue = p.waitFor();
			System.out.println(fileName + " is analyzing... : " + exitValue);
			return p;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	public String getSettingFileLocation() {
		return settingFile;
	}

	public String getOutputLocation() {
		return getMetPath(this.getSettingFileLocation());
	}

	private static String getMetPath(String settingFilePath) {
		File settingFile = new File(settingFilePath);
		FileInputStream fis;
		try {
			fis = new FileInputStream(settingFile);
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					fis));
			Pattern p = Pattern.compile("-op\\s+(.*)");
			Matcher matcher = p.matcher("");
			String line = null;
			while ((line = reader.readLine()) != null) {
				matcher.reset(line);
				while (matcher.find()) {
					String resultStr = matcher.replaceAll("$1");
					return resultStr.replaceAll("\"", "");
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}
}
